package org.flexthinker.binding.form.support
{
    import org.flexthinker.binding.form.ValidatingFormModel;

    import org.flexthinker.binding.validation.FormModelValidator;
    import org.flexthinker.binding.validation.ValidationResultsModel;
    import org.flexthinker.binding.validation.support.DefaultValidationResults;
    import org.flexthinker.binding.validation.support.DefaultValidationResultsModel;
    import org.flexthinker.binding.validation.support.RulesValidator;

    import mx.events.PropertyChangeEvent;

    /**
     * An Extension of DefaultFormModel with support for validation.
     */
    public class DefaultValidatingFormModel extends DefaultFormModel implements ValidatingFormModel
    {
        private var validationResultsModel:DefaultValidationResultsModel = new DefaultValidationResultsModel();
        private var validating:Boolean = true;

        private var currentValidator:FormModelValidator;

        private var defaultValidator:FormModelValidator;

        public function DefaultValidatingFormModel( domainObject:Object, buffered:Boolean = true )
        {
            super( domainObject, buffered );
            init();
        }

        override public function isCommittable():Boolean
        {
            return !getValidationResults().getHasErrors();
        }

        public function getValidationResults():ValidationResultsModel
        {
            return validationResultsModel;
        }

        public function validate():void
        {
            if( isValidating() )
            {
                validateAfterPropertyChanged( null );
            }
        }

        public function getValidator():FormModelValidator
        {
            if( currentValidator != null )
            {
                return currentValidator;
            }
            return defaultValidator;
        }

        public function setValidator( validator:FormModelValidator ):void
        {
            currentValidator = validator;
            currentValidator.setFormModel( this );
            validate();
        }

        public function isValidating():Boolean
        {
            /*
             if (validating && isEnabled()) {
             if (getParent() instanceof ValidatingFormModel)
             {
             return ((ValidatingFormModel)getParent()).isValidating();
             }
             return true;
             }
             return false;
             */
            return validating;
        }

        public function setValidating( validating:Boolean ):void
        {
            if( this.validating != validating )
            {
                this.validating = validating;

                if( this.validating )
                {
                    validate();
                }
                else
                {
                    //validationResultsModel.clearAllValidationResults();
                }
            }
        }

        // -------------------
        //   internal methods
        // ---------------------
        private function init():void
        {
            defaultValidator = new RulesValidator();
        }

        override protected function validateAfterPropertyChanged( formProperty:String, event:PropertyChangeEvent = null ):void
        {
            super.validateAfterPropertyChanged( formProperty, event );

            var validator:FormModelValidator = getValidator();
            if( isValidating() && validator != null )
            {
                var validationResults:DefaultValidationResults = new DefaultValidationResults();

                if( formProperty != null )
                {
                    // get previous messages
                    validationResults.addAllMessages( validationResultsModel.getMessages() );
                    // and clear only the messages for the currentProperty
                    validationResults.clearMessagesForProperty( formProperty );
                    validationResults.addAllMessages( validator.validateProperty( formProperty ).getMessages() );
                }
                else
                {
                    validationResults.addAllMessages( validator.validateAll().getMessages() );
                }

                validationResultsModel.updateValidationResults( validationResults );
            }

        }
    }
}